import { Component, OnInit } from '@angular/core'
import { FormBuilder } from '@angular/forms'
import { AcquirerNewBaseClass } from '../baseClass'
import { AcquirerStoreService } from '../acquirer-store.service'
import { WXChannel, ALPChannel, QrChannel, UPIChannel } from '@shared/interfaces/acquirer'
import { IFormItem, FormItemType, ChanCodeLabel, ChanCodeValue } from '@shared/interfaces/common'
import { CurrencyService } from '@shared/services/currency.service'
import { ChannelAddMinusService } from '@shared/services/channelAddMinus.service'
import { zip } from 'rxjs'
import { numScale, encryptLongText, channelOptionSort } from 'app/utils/helpers'
import { PageService } from '@shared/services/page.service'
import { AcquirerService } from '../../acquirer.service'
import { NzModalService } from 'ng-zorro-antd'
import { deepCopy } from '@delon/util'
import { UPIService } from './config-UPI.service'
import { WXPService } from './config-WXP.service'
import { ALPService } from './config-ALP.service'

import { I18NService } from '@core'
import { ECategoryUrl } from '@shared/interfaces/trade'
import { TRUService } from './config-TRU.service'

@Component({
  selector: 'app-acquirer-new-qrcode-channel',
  templateUrl: './qrcode-channel.component.html',
  providers: [ChannelAddMinusService],
})
export class AcquirerNewQrcodeChannelComponent extends AcquirerNewBaseClass implements OnInit {
  loading = true

  channelNameOptions = []

  chanCodeFormItem: IFormItem = {
    label: this.trans('BIZ.ACQUIRER.OTHER.CHANNEL.PAYMENT_CHANNEL'),
    errTips: {
      required: this.trans('VALIDATION.REQUIRED_SELECT', {
        name: this.trans('BIZ.ACQUIRER.OTHER.CHANNEL.PAYMENT_CHANNEL'),
      }),
    },
    errTip: this.trans('VALIDATION.REQUIRED_SELECT', {
      name: this.trans('BIZ.ACQUIRER.OTHER.CHANNEL.PAYMENT_CHANNEL'),
    }),
    formControlName: 'chanCode',
    type: FormItemType.SELECT,
    compareFn: (o1, o2) => o1 === o2,
    multiple: 'default',
    allowClear: true,
    options: this.channelNameOptions,
    change: this.handleChannelChange.bind(this),
  }

  wxFormItems: IFormItem[] = []

  alipayFormItems: IFormItem[] = []

  upiFormItems: IFormItem[] = []

  formItemType = FormItemType

  currencyOptions = []

  currencyCodeOptions = []

  formItems: IFormItem[] = [this.chanCodeFormItem]

  constructor(
    public fb: FormBuilder,
    public modal: NzModalService,
    public acquirerStore: AcquirerStoreService,
    public addMinusService: ChannelAddMinusService,
    public currencyService: CurrencyService,
    public pageService: PageService,
    public acquirerService: AcquirerService,
    private i18n: I18NService,
    private configUPIService: UPIService,
    private configWXPService: WXPService,
    private configALPService: ALPService,
    private configTRUService: TRUService
  ) {
    super(fb, acquirerStore)
  }

  ngOnInit() {
    this.initChannelNameOptions()
    this.initCurrencyOptions()
  }

  initChannelNameOptions(): void {
    for (const name in ChanCodeLabel) {
      const option = {
        label: ChanCodeLabel[name],
        value: ChanCodeValue[name],
      }
      this.channelNameOptions.push(option)
    }
    // 按照字母序排序
    this.channelNameOptions.sort(channelOptionSort)
    this.initFormItems()
  }

  initCurrencyOptions(): void {
    zip(this.currencyService.getCurrencyOptions(), this.currencyService.getCurrencySearchOptions()).subscribe(value => {
      const [currencies, currencyCodes] = value
      if (currencies.length === 0 || currencyCodes.length === 0) {
        return
      }
      this.currencyOptions = currencies
      this.currencyCodeOptions = currencyCodes
      this.initAddMinus()
      this.loading = false
    })
  }

  initFormItems(): void {
    this.formItems = [this.chanCodeFormItem]
  }

  initAddMinus(): void {
    const { qrChannels } = this.acquirer
    const generateFunc = (channel: WXChannel | ALPChannel) => {
      const { chanCode } = channel
      const rule = [
        this.generateValidateRules.call(this, chanCode || ChanCodeValue.WXP, channel),
        this.getAdditionalValidateRules(chanCode || ChanCodeValue.WXP, channel),
      ]
      return {
        rule,
        formItems: this.generateFormItems(chanCode),
      }
    }
    this.addMinusService.init(generateFunc, new QrChannel(), qrChannels)
  }

  generateValidateRules(chanCode: string, channel?: WXChannel | ALPChannel | UPIChannel): { [key: string]: any } {
    switch (chanCode) {
      case ChanCodeValue.WXP:
        return this.configWXPService.genWXValidateRules(channel as WXChannel)

      case ChanCodeValue.ALP:
        return this.configALPService.genALPValidateRules(channel as ALPChannel)

      case ChanCodeValue.UPI:
        return this.configUPIService.genUPIValidateRules(channel as UPIChannel)

      // case ChanCodeValue.TRU:
      //   break

      // case ChanCodeValue.VIS:
      //   break

      // case ChanCodeValue.MCC:
      //   break

      // case ChanCodeValue.FPS:
      //   break

      case ChanCodeValue.TRU:
        return this.configTRUService.genTRUalidateRules(channel as WXChannel)
      default:
        return this.configWXPService.genWXValidateRules(channel as WXChannel)
    }
  }

  getAdditionalValidateRules(chanCode: string, channel?: WXChannel | ALPChannel | UPIChannel): { [key: string]: any } {
    switch (chanCode) {
      case ChanCodeValue.ALP:
        return this.configALPService.genALPAdditionalValidateRules(channel as ALPChannel)
      default:
        return {}
    }
  }

  generateFormItems(chanCode: string): IFormItem[] {
    switch (chanCode) {
      case ChanCodeValue.WXP:
        return [
          this.chanCodeFormItem,
          ...deepCopy(this.configWXPService.genWXFormItems(this.currencyOptions, this.handleChanMerIdChange.bind(this))),
        ]
      case ChanCodeValue.ALP:
        return [
          this.chanCodeFormItem,
          ...deepCopy(
            this.configALPService.genALPFormItems(this.currencyOptions, this.currencyCodeOptions, this.handleChanMerIdChange.bind(this)),
          ),
        ]
      case ChanCodeValue.UPI:
        return [
          this.chanCodeFormItem,
          ...deepCopy(
            this.configUPIService.genUPIFormItems(this.currencyOptions, this.currencyCodeOptions, this.handleChanMerIdChange.bind(this)),
          ),
        ]
      default:
        return [this.chanCodeFormItem]
    }
  }

  handleChannelChange(chanCode, index): void {
    this.addMinusService.formItemsArr[index] = this.generateFormItems(chanCode)
    const formGroup = this.addMinusService.generateValidateForm([
      this.generateValidateRules(chanCode),
      this.getAdditionalValidateRules(chanCode),
    ])
    formGroup.get('chanCode').setValue(chanCode)
    this.addMinusService.validateForms[index] = formGroup
    this.addMinusService.isNeedValidateArr[index] = true
  }

  handleChanMerIdChange(event, index: number): void {
    const chanCode = this.addMinusService.validateForms[index].get('chanCode').value
    const chanMerID = event.target.value
    if (!this.getChanMerIDValid(index, chanMerID)) {
      return
    }
    this.acquirerService.getExistedChannel(chanCode, chanMerID, ECategoryUrl.qr).subscribe(channel => {
      this.modal.confirm({
        nzTitle: `<i>${this.trans('BIZ.ACQUIRER.CHANNEL.FOUND_MATCH_CHANNEL')}</i>`,
        nzContent: `<b>${this.trans('BIZ.ACQUIRER.CHANNEL.CONFIRM_TO_LOAD_CHANNEL_FOLLOW')} ${chanMerID}</b>`,
        nzOnOk: () => this.addMinusService.loadChannel(channel, index),
        nzOnCancel: () => this.clearChanCode(index),
      })
    })
  }

  getChanMerIDValid(index: number, chanMerID: string): boolean {
    this.addMinusService.checkChanMerIDUnique(index, chanMerID)
    return this.addMinusService.validateForms[index].get('chanMerID').valid
  }

  clearChanCode(index: number): void {
    this.addMinusService.validateForms[index].get('chanMerID').setValue(null)
  }

  checkValid(): boolean {
    this.addMinusService.makeDirty()
    const valid = this.addMinusService.valid
    valid ? this.pushDataToStore() : (this.acquirer.qrChannels = [])
    return valid
  }

  pushDataToStore(): void {
    const qrChannels = this.addMinusService.values
    qrChannels.forEach(channel => {
      /**
       * 费率转成数字
       * 长加密私钥
       */
      if (channel.chanCode !== ChanCodeValue.TRU) {
        channel.fee = numScale(channel.fee, -2)
      }
      if (!!channel.privateKeyArray && typeof channel.privateKeyArray === 'string') {
        channel.privateKeyArray = encryptLongText(channel.privateKeyArray)
      }
      if (channel.chanCode === ChanCodeValue.ALP) {
        this.handleALPBeforePushToStore(channel)
      }
    })
    this.acquirer.qrChannels = qrChannels
  }

  computeChannelSectionHeader(idx: number): string {
    return `${this.trans('BIZ.ACQUIRER.OTHER.CHANNEL.CHANNEL_CONFIG')} ${idx + 1}`
  }

  trans(str: string, params?: Object): string {
    return this.i18n.fanyi(str, params)
  }

  handleALPBeforePushToStore(channel) {
    /* 转化一下 sftp 结构 */
    channel.sftp = {
      username: channel!.sftpUsername,
      password: channel.sftpPassword,
      filePath: channel.sftpFilePath,
    }
    delete channel.sftpUsername
    delete channel.sftpPassword
    delete channel.sftpFilePath

    /** switch 处理 */
    if (!channel.isSupportPayment) {
      delete channel.signKey
    }

    if (!channel.isSupportSettleCurr) {
      delete channel.settleCurrency
    }

    if (!channel.isSupportPreAuth) {
      delete channel.appID
      delete channel.publicKey
      delete channel.privateKey
    }
  }
}
